#region

using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using WorkData.ElasticSearch;
using WorkData.ElasticSearch.Entity;
using WorkData.ElasticSearch.Interfaces;
using WorkData.Util.Common.Extensions;
using WorkData.Util.Common.Helpers;
using WorkDataEs.WorkDataElasticSearchs.Contents.Dto;

#endregion

namespace WorkDataEs.WorkDataElasticSearchs.Contents
{
    public class ContentService : IContentService
    {
        private readonly IIndexProvider _indexProvider;
        private readonly ISearchProvider _searchProvider;
        private readonly IDeleteProvider _deleteProvider;
        private readonly IUpdateProvider _updateProvider;

        public ContentService(
            IIndexProvider indexProvider, ISearchProvider searchProvider,
            IDeleteProvider deleteProvider, IUpdateProvider updateProvider)
        {
            _indexProvider = indexProvider;
            _searchProvider = searchProvider;
            _deleteProvider = deleteProvider;
            _updateProvider = updateProvider;
        }

        /// <summary>
        ///     批量新增
        /// </summary>
        /// <param name="content"></param>
        /// <param name="index"></param>
        public void BlukIndex(List<Content> content, string index)
        {
            _indexProvider.BulkIndex(content, index);
        }

        /// <summary>
        ///     Search
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="requestContentDto"></param>
        public ContentResponse Search(int pageIndex, int pageSize, RequestContentDto requestContentDto)
        {
            var elasticsearchclient = WorkData.ElasticSearch.Impl.NullElasticClient.Instance;
            var elasticsearchPage = new ElasticsearchPage<Content>()
            {
                PageIndex = pageIndex,
                PageSize = pageSize
            };
            var searchRequest = elasticsearchPage.InitSearchRequest("index_cuss");
            #region terms 分组

            var terms = new List<IFieldTerms>();
            var classificationGroupBy = "searchKey_classification";
            var brandGroupBy = "searchKey_brand";

            #endregion

            #region 封装查询
            //var predicateList = new List<IPredicate>();
            //////分类ID
            ////if (requestContentDto.CategoryId != null)
            ////    predicateList.Add(Predicates.Field<Content>(x => x.ClassificationCode, ExpressOperator.Like,
            ////        requestContentDto.CategoryId));
            ////else
            ////    terms.Add(Predicates.FieldTerms<Content>(x => x.ClassificationGroupBy, classificationGroupBy, 200));

            //////品牌
            ////if (string.IsNullOrWhiteSpace(requestContentDto.Brand))
            ////    terms.Add(Predicates.FieldTerms<Content>(x => x.BrandGroupBy, brandGroupBy, 200));
            //////供应商名称
            ////if (!string.IsNullOrWhiteSpace(requestContentDto.BaseType))
            ////    predicateList.Add(Predicates.Field<Content>(x => x.BaseType, ExpressOperator.Like,
            ////        requestContentDto.BaseType));
            //////是否自营
            ////if (requestContentDto.IsSelfSupport == 1)
            ////    predicateList.Add(Predicates.Field<Content>(x => x.IsSelfSupport, ExpressOperator.Eq,
            ////        requestContentDto.IsSelfSupport));
            //////最大价格
            ////if (requestContentDto.MaxPrice != null)
            ////    predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Le,
            ////        requestContentDto.MaxPrice));
            //////最小价格
            ////if (requestContentDto.MinPrice != null)
            ////    predicateList.Add(Predicates.Field<Content>(x => x.UnitPrice, ExpressOperator.Ge,
            ////        requestContentDto.MinPrice));

            ////关键词
            //if (!string.IsNullOrWhiteSpace(requestContentDto.SearchKey))
            //    predicateList.Add(Predicates.Field<Content>(x => x.IsSelfSupport, ExpressOperator.Eq, 0));

            ////规整排序
            //var sortConfig = SortOrderRule(requestContentDto.SortKey);
            //var sorts = new List<ISort>
            //{
            //    Predicates.Sort<Content>(sortConfig.Key, sortConfig.SortOrder)
            //};

            //var predicate = Predicates.Group(GroupOperator.And, predicateList.ToArray());

            ////构建或查询
            //var predicateListOr = new List<IPredicate>();
            ////if (!string.IsNullOrWhiteSpace(requestContentDto.Brand))
            ////{
            ////    var array = requestContentDto.Brand.Split(',').ToList();
            ////    predicateListOr.AddRange(array.Select(item => Predicates.Field<Content>(x => x.Title, ExpressOperator.Like, item)));
            ////}

            //var predicateOr = Predicates.Group(GroupOperator.Or, predicateListOr.ToArray());

            //var predicatecCombination = new List<IPredicate> { predicate };
            //var pgCombination = Predicates.Group(GroupOperator.And, predicatecCombination.ToArray());

            //searchRequest.InitQueryContainer(pgCombination)
            //    .InitSort(sorts)
            //    .InitHighlight(requestContentDto.HighlightConfigEntity)
            //    .InitGroupBy(terms);


            //var data = _searchProvider.SearchPage(searchRequest);
            //QueryContainer termQuery = new TermRangeQuery() { Field = "key", GreaterThan = "3" };//大于,小于,等于系列查询

            //var searchResults = d.Search<Content>(s => s
            //   .Query(x => termQuery)
            //   .Sort(x => x.Ascending(a => a.Key))
            //    .From(0)
            //    .Size(3)
            //   );

            #endregion


            #region 使用原生查询,自由组装表达式

            //var ff = d.Search<Content>(x => x.Query(q=>q.Term(p => p.IsSelfSupport, 0)));

            //var termQuery = new MatchPhraseQuery() { Field = "title", Query = "康" };//模糊查询, 模糊查询 (You can use % in the value to do wilcard searching)
            //var data = d.Search<Content>(s => s
            //   .From(0)
            //   .Size(5)
            //   .Query(x=>termQuery)
            //   );

            //var termQuery = new TermQuery() { Field = "resourceStatus", Value = 1 };//精确查询, 精准匹配 term（主要用于精确匹配哪些值，比如数字，日期，布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)： ）
            //var termQuery2 = new TermQuery() { Field = "key", Value = 0 };//精确查询
            //termQuery = (termQuery && termQuery2);
            //var data = d.Search<Content>(s => s
            //   .From(0)
            //   .Size(5)
            //   .Query(x => termQuery)
            //   );

            /*
             *区间查询
             * GreaterThan：大于,
             * GreaterThanOrEqualTo：大于等于,
             * LessThan：小于,
             * LessThanOrEqualTo：小于等于,
             */
            // var termQuery = new TermRangeQuery() { Field = "key", GreaterThan = "3" };
            //var data = elasticsearchclient.Search<Content>(s => s
            //   .Query(x => termQuery)
            //    .From(0)
            //    .Size(10)
            //   );


            //var termQuery = new TermsQuery() { Field = "key", Terms = new List<string>() { "0", "1" } };//In查询
            //var data = elasticsearchclient.Search<Content>(s => s
            //   .Query(x => termQuery)
            //    .From(0)
            //    .Size(10)
            //   );


            /*
             * bool查询
             * Must：所有分句必须全部匹配，与 AND 相同
             * Should：至少有一个分句匹配，与 OR 相同
             * MustNot：所有分句都必须不匹配，与 NOT 相同
             * */
            var data = elasticsearchclient.Search<Content>(s => s
               .Query(x => x.Bool(a => a.Must(mt => mt.TermRange(p => p.Field(f => f.Key).GreaterThan("0").LessThan("4")))))
                .From(0)
                .Size(10)
                .Sort(st => st.Ascending(asc => asc.ResourceStatus))//排序
               );
            #endregion

            if (data == null)
            {
                Console.WriteLine("未查到任何数据");
                return new ContentResponse();
            }
            else
            {

                #region terms 分组赋值

                //var classificationResponses = requestContentDto.CategoryId != null
                //    ? null
                //    : data.Aggregations.Terms(classificationGroupBy).Buckets
                //        .Select(x => new ClassificationResponse
                //        {
                //            Key = x.Key.ToString(),
                //            DocCount = x.DocCount
                //        }).ToList();

                //var brandResponses = !string.IsNullOrWhiteSpace(requestContentDto.Brand)
                //    ? null
                //    : data.Aggregations.Terms(brandGroupBy).Buckets
                //        .Select(x => new BrandResponse
                //        {
                //            Key = x.Key.ToString(),
                //            DocCount = x.DocCount
                //        }).ToList();

                #endregion

                //初始化

                #region 高亮
                Console.WriteLine(data.Hits.FirstOrDefault());
                var titlePropertySearchName = (PropertySearchNameAttribute)
                    LoadAttributeHelper.LoadAttributeByType<Content, PropertySearchNameAttribute>(x => x.Title);

                var list = data.Hits.Select(c => new Content
                {
                    Key = c.Source.Key,
                    Title = (string)c.Highlights.Highlight(c.Source.Title, titlePropertySearchName.Name),
                    ImgUrl = c.Source.ImgUrl,
                    BaseType = c.Source.BaseType,
                    BelongMemberName = c.Source.BelongMemberName,
                    Brand = c.Source.Brand,
                    Code = c.Source.Code,
                    BrandFirstLetters = c.Source.BrandFirstLetters,
                    ClassificationName = c.Source.ClassificationName,
                    ResourceStatus = c.Source.ResourceStatus,
                    BrandGroupBy = c.Source.BrandGroupBy,
                    ClassificationGroupBy = c.Source.ClassificationGroupBy,
                    ClassificationCode = c.Source.ClassificationCode,
                    IsSelfSupport = c.Source.IsSelfSupport,
                    UnitPrice = c.Source.UnitPrice
                }).ToList();

                #endregion
                var contentResponse = new ContentResponse
                {
                    Records = (int)data.Total,
                    PageIndex = elasticsearchPage.PageIndex,
                    PageSize = elasticsearchPage.PageSize,
                    Contents = list,
                    //BrandResponses = brandResponses,
                    //ClassificationResponses = classificationResponses
                    d = data,
                };
                return contentResponse;

            }

        }

        /// <summary>
        ///     删除指定数据
        /// </summary>
        public void DeleteByQuery(string key)
        {
            var request = new DeleteByQueryRequest<Content>("content_test");
            var predicateList = new List<IPredicate>
            {
                Predicates.Field<Content>(x => x.Key, ExpressOperator.Eq, key)
            };
            var predicate = Predicates.Group(GroupOperator.And, predicateList.ToArray());
            request.InitDelteQueryContainer(predicate);

            _deleteProvider.DeleteByQuery(request);
        }

        /// <summary>
        ///     更新数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="data"></param>
        public void UpdateByKey(string key, object data)
        {
            var request = new UpdateRequest<Content, object>("content_test", "content_test", key)
            {
                Doc = data
            };
            _updateProvider.Update(request);
        }

        /// <summary>
        ///     新增
        /// </summary>
        /// <param name="content"></param>
        /// <param name="index"></param>
        public void Index(Content content, string index)
        {
            _indexProvider.Index(content, index);
        }

        /// <summary>
        ///     排序规则验证
        /// </summary>
        /// <param name="sortKey"></param>
        private SortKeyConfig SortOrderRule(string sortKey)
        {
            //初始化对象
            var sortKeyConfig = new SortKeyConfig { Key = "_score", SortOrder = SortOrder.Descending };
            //设置默认值
            if (string.IsNullOrWhiteSpace(sortKey) || !sortKeyConfig.SortKeyConfigs.Contains(sortKey))
                return sortKeyConfig;

            //转换为小写
            sortKey = sortKey.ToLower();

            var orderArray = sortKey.BreakUpOptions('-');
            if (orderArray == null || orderArray.Length != 2)
                return sortKeyConfig;

            var key = orderArray.FirstOrDefault();
            var sortOrder = orderArray.LastOrDefault();

            //赋值
            sortKeyConfig.Key = key;
            sortKeyConfig.SortOrder = sortOrder == "desc" ? SortOrder.Descending : SortOrder.Ascending;
            return sortKeyConfig;
        }

    }
}